package com.gitee.wsl.common.chart.sample.bar

import android.graphics.Canvas
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.render.background.axis.line.CategoryLineAxis
import com.gitee.wsl.common.chart.render.background.axis.line.DataLineAxis
import com.gitee.wsl.common.chart.sample.bar.model.BarData
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.round
import com.gitee.wsl.jvm.math.sub


/**
 * @ClassName StackBarChart
 * @Description  堆叠图基类
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */

class StackBarChart: BarChart() {
     //val flatBar: FlatBar = FlatBar()
     var isTotalLabelVisible = true

    override fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.STACKBAR
    }


    private fun getHBarHeight(YSteps: Float): Float {
        var barHeight = Math.round(Math.mul(YSteps, 0.5f), 2)
        val maxHeight: Float = flatBar.barMaxPxHeight
        if (maxHeight.compareTo(0.0f) == 1 && barHeight.compareTo(maxHeight) == 1) {
            barHeight = maxHeight
        }
        return barHeight
    }

    private fun getVBarWidth(XSteps: Float): Float {
        var barWidth: Float = Math.mul(XSteps, 0.5f)
        val maxWidth: Float = flatBar.barMaxPxWidth
        if (maxWidth.compareTo(0.0f) == 1 &&
            barWidth.compareTo(maxWidth) == 1
        ) {
            barWidth = maxWidth
        }
        return barWidth
    }

     override fun drawHorizontalBar(canvas: Canvas, dataAxis: DataLineAxis, categoryAxis: CategoryLineAxis): Boolean {
        
        val axisScreenWidth = getPlotScreenWidth()
        val axisDataRange: Float = dataAxis.axisRange

        //步长
        val YSteps = getVerticalYSteps(getCateTickCount(categoryAxis))
        val barHeight = getHBarHeight(YSteps)
        val cateSize: Int = categoryAxis.dataSet.size
        var dataSize = 0
        var labelY = 0f

        //分类轴	
        for (r in 0 until cateSize) {
            var currentX: Float = bodyViewport.left
            var currentY: Float = Math.sub(bodyViewport.bottom, Math.mul((r + 1).toFloat(), YSteps))
            var total = 0.0f
            labelY = currentY
            if (ChartEnum.BarCenterStyle.SPACE == this.barCenterStyle) {
                labelY = Math.add(currentY, Math.div(YSteps, 2f))
                currentY = labelY
            }

            //得到数据源
            val chartDataSource: List<BarData> = this.dataSet
            if (chartDataSource.isEmpty()) continue
            dataSize = chartDataSource.size
            for (i in 0 until dataSize)  //轴上的每个标签各自所占的高度
            {
                val bd = chartDataSource[i]

                flatBar.barPaint.color = bd.color
                if (bd.dataSet.size < r + 1) continue

                //参数值与最大值的比例  照搬到 y轴高度与矩形高度的比例上来	
                val bv = bd.dataSet[r]
                total = Math.add(total, bv)
                var valuePostion = 0.0f
                if (i == 0) {
                    val t = Math.sub(bv, dataAxis.axisMin)
                    valuePostion = Math.mul(axisScreenWidth, Math.div(t, axisDataRange))
                } else {
                    val t2: Float = Math.div(bv, axisDataRange)
                    valuePostion = Math.mul(axisScreenWidth, t2)
                }

                //宽度                	
                val topY: Float = Math.sub(currentY, barHeight / 2)
                val rightX: Float = Math.add(currentX, valuePostion)
                val bottomY: Float = Math.add(currentY, barHeight / 2)
                flatBar.renderBar(currentX, topY, rightX, bottomY, canvas)

                //保存位置
                saveBarRectFRecord(
                    i,
                    r,
                    currentX + moveX,
                    topY + moveY,
                    rightX + moveX,
                    bottomY + moveY
                )

                //显示焦点框
                drawFocusRect(canvas, i, r, currentX, topY, rightX, bottomY)
                val labelLeftX: Float = Math.add(currentX, valuePostion / 2)

                //在柱形的顶端显示上批注形状
                drawAnchor(this.anchorSet, i, r, canvas, labelLeftX, labelY, 0.0f)

                //柱形的当前值
                flatBar.renderBarItemLabel(getFormatterItemLabel(bv), labelLeftX, labelY, canvas)
                currentX = Math.add(currentX, valuePostion)
            }

            //合计		
            if (isTotalLabelVisible) {
                val t = Math.sub(total,  dataAxis.axisMin)
                val totalPostion: Float = Math.mul(Math.div(axisScreenWidth, axisDataRange), t)
                flatBar.renderBarItemLabel(
                    getFormatterItemLabel(total),
                    Math.add(bodyViewport.left, totalPostion), currentY, canvas
                )
            }
        }
        return true
    }


    override fun drawVerticalBar(canvas: Canvas, dataAxis: DataLineAxis, categoryAxis: CategoryLineAxis): Boolean {
        //得到分类轴数据集
        val dataSet: List<String> = categoryAxis.dataSet ?: return false

        //得到数据源
        val chartDataSource: List<BarData> = this.dataSet
            ?: return false
        val XSteps = getVerticalXSteps(dataSet.size + 1)
        val axisScreenHeight = getAxisScreenHeight()
        val axisDataHeight: Float = dataAxis.axisRange
        val barWidth = getVBarWidth(XSteps) // MathExt.mul(XSteps,0.5f);	
        var currentX = 0.0f
        var currentY = 0.0f
        var labelX = 0f
        val dataSize = dataSet.size
        var sourceSize = 0
        for (r in 0 until dataSize)  //轴上的每个标签
        {
            currentX = Math.add(bodyViewport.left, Math.mul((r + 1).toFloat(), XSteps))
            currentY = bodyViewport.bottom
            var total = 0.0f
            labelX = currentX
            if (ChartEnum.BarCenterStyle.SPACE == this.barCenterStyle) {
                labelX = Math.sub(currentX, Math.div(XSteps, 2f))
                currentX = labelX
            }
            sourceSize = chartDataSource.size
            for (i in 0 until sourceSize)  //各自所占的高度
            {
                val bd = chartDataSource[i]

                flatBar.barPaint.color = bd.color
                if (bd.dataSet.size < r + 1) continue

                //参数值与最大值的比例  照搬到 y轴高度与矩形高度的比例上来	
                val bv = bd.dataSet[r]
                total = Math.add(total, bv)
                var valuePostion = 0.0f
                if (i == 0) {
                    val t = Math.sub(bv,  dataAxis.axisMin)
                    valuePostion = Math.mul(axisScreenHeight, Math.div(t, axisDataHeight))
                } else {
                    val t2 = Math.div(bv, axisDataHeight)
                    valuePostion = Math.mul(axisScreenHeight, t2)
                }

                //柱形
                val leftX: Float = Math.sub(currentX, barWidth / 2)
                val topY: Float = Math.sub(currentY, valuePostion)
                val rightX: Float = Math.add(currentX, barWidth / 2)
                flatBar.renderBar(leftX, topY, rightX, currentY, canvas)
                //保存位置
                saveBarRectFRecord(
                    i,
                    r,
                    leftX + moveX,
                    topY + moveY,
                    rightX + moveX,
                    currentY + moveY
                )

                //显示焦点框
                drawFocusRect(canvas, i, r, leftX, topY, rightX, currentY)
                val labelLeftY: Float = Math.sub(currentY, valuePostion / 2)

                //在柱形的顶端显示上批注形状
                drawAnchor(this.anchorSet, i, r, canvas, labelX, labelLeftY, 0.0f)

                //柱形的当前值
                flatBar.renderBarItemLabel(
                    getFormatterItemLabel(bv),
                    labelX, labelLeftY, canvas
                )
                currentY = Math.sub(currentY, valuePostion)
            }

            //合计		
            if (isTotalLabelVisible) {
                val per = Math.sub(total,  dataAxis.axisMin)
                val totalPostion = Math.mul(Math.div(axisScreenHeight, axisDataHeight), per)
                flatBar.renderBarItemLabel(
                    getFormatterItemLabel(total),
                    currentX, Math.sub(bodyViewport.bottom, totalPostion), canvas
                )
            }
        }
        return true
    }
}